package com.ptone.messageCenter.config.exceptionConfig;

import com.ptone.messageCenter.common.response.ErrCode;
import com.ptone.messageCenter.common.response.Result;
import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 错误信息拦截器
 */
@Configuration
@RestControllerAdvice
public class MyExceptionHandler {

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    @ResponseBody
    @ExceptionHandler({Exception.class})
    public Object handleException(Exception e) {
        //不支持的请求方式
        if (HttpRequestMethodNotSupportedException.class == e.getClass())
            return Result.fail(ErrCode.REQUEST_TYPE_NO_SUPPORT, ((HttpRequestMethodNotSupportedException) e).getMethod());
        //不支持的传参方式
        if (HttpMediaTypeNotSupportedException.class == e.getClass())
            return Result.fail(ErrCode.PARAMS_TYPE_MUST_BE_JSON, e);
        //参数非空或类型错误
        if (e instanceof HttpMessageNotReadableException || e instanceof MissingServletRequestParameterException)
            return Result.fail(ErrCode.CHECK_PARAMS_FAIL, e.getMessage());
        //@Valid 参数校验异常
        if (e instanceof MethodArgumentNotValidException) {
            List<FieldError> fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
            Map<String, String> error = fieldErrors.stream()
                    .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            return Result.fail(ErrCode.CHECK_PARAMS_FAIL, error);
        }
        //参数验证异常
        if (e instanceof BindException) {
            BindingResult result = ((BindException) e).getBindingResult();
            Map<String, String> error = result.getAllErrors().stream()
                    .collect(Collectors.toMap(x ->
                                    Optional.ofNullable(x)
                                            .filter(y -> y instanceof FieldError)
                                            .map(y -> (FieldError) y)
                                            .map(FieldError::getField)
                                            .orElse(x.getObjectName()),
                            ObjectError::getDefaultMessage
                    ));
            return Result.fail(ErrCode.CHECK_PARAMS_FAIL, error);
        }
        //sql执行异常
        if (e instanceof BadSqlGrammarException)
            LOGGER.error("捕获SQL异常:  ", e);
        //浏览器关闭连接异常
        if (ClientAbortException.class == e.getClass() || MultipartException.class == e.getClass()) {
            LOGGER.info("浏览器关闭了连接");
            return Result.fail(ErrCode.BROWSER_CONNECTION_CLOSED);
        }
        //JSON化失败异常
        if (HttpMessageNotWritableException.class == e.getClass())
            return null;
        LOGGER.error("捕获未处理异常:  ", e);
        return Result.fail(ErrCode.SYSTEM_ERROR, e);
    }

}